package cn.com.thinvent.dispatch.service.biz.impl;

import cn.com.thinvent.dispatch.dao.MajorExpenseDetailsMapper;
import cn.com.thinvent.dispatch.dao.MajorExpensesDetailsMappingMapper;
import cn.com.thinvent.dispatch.dao.MajorExpensesMapper;
import cn.com.thinvent.dispatch.entity.MajorExpenseDetails;
import cn.com.thinvent.dispatch.entity.MajorExpenses;
import cn.com.thinvent.dispatch.entity.MajorExpensesDetailsMapping;
import cn.com.thinvent.dispatch.entity.request.Detail;
import cn.com.thinvent.dispatch.entity.request.ExpenseRequest;
import cn.com.thinvent.dispatch.entity.response.ExpenseResponse;
import cn.com.thinvent.dispatch.entity.response.PagedGridResult;
import cn.com.thinvent.dispatch.service.biz.ExpenseService;
import cn.com.thinvent.dispatch.service.biz.util.DataConvertUtils;
import cn.com.thinvent.dispatch.service.biz.util.KeyGenerator;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Component
public class ExpenseServiceImpl implements ExpenseService {

    @Resource
    private MajorExpensesMapper majorExpensesMapper;

    @Resource
    private MajorExpensesDetailsMappingMapper majorExpensesDetailsMappingMapper;

    @Resource
    private MajorExpenseDetailsMapper majorExpenseDetailsMapper;

    @Override
    public PagedGridResult<ExpenseResponse> getExpenses(Integer page, Integer pageSize, String expenseName) {
        int offset = (page - 1) * pageSize;
        List<MajorExpenses> expenses = majorExpensesMapper.getExpenses(offset, pageSize, expenseName);
        int total = majorExpensesMapper.countExpenses(expenseName);

        List<ExpenseResponse> expenseResponses = new ArrayList<>();
        if(CollectionUtils.isNotEmpty(expenses)) {
            DataConvertUtils.convertDOList2DTOList(expenses, expenseResponses, ExpenseResponse.class);
        }
        PagedGridResult<ExpenseResponse> pagedGridResult = new PagedGridResult<>();
        pagedGridResult.setPage(page);
        pagedGridResult.setTotal((int) Math.ceil((double) total / pageSize));
        pagedGridResult.setRecords(total);
        pagedGridResult.setRows(expenseResponses);

        return pagedGridResult;
    }

    @Override
    @Transactional
    public Integer addExpense(ExpenseRequest expense) {
        MajorExpenses majorExpenses = new MajorExpenses();
        Date date = new Date();
        List<MajorExpenseDetails> majorExpensesList = new ArrayList<>();
        List<MajorExpensesDetailsMapping> majorExpensesMappings = new ArrayList<>();
        if(null != expense) {
            DataConvertUtils.convertDTO2DO(expense, majorExpenses);
            // 设置主键id
            majorExpenses.setId(KeyGenerator.generateKey());
            majorExpenses.setCreatedAt(date);
            majorExpenses.setUpdatedAt(date);
            List<Detail> details = expense.getDetails();
            DataConvertUtils.convertDOList2DTOList(details, majorExpensesList, MajorExpenseDetails.class);
        }
        majorExpensesList.stream().forEach(majorExpenseDetails -> {
            majorExpenseDetails.setCreatedAt(date);
            majorExpenseDetails.setUpdatedAt(date);
            // 设置主键id
            majorExpenseDetails.setId(KeyGenerator.generateKey());
            // 设置重大开销id
            majorExpenseDetails.setMajorExpenseId(majorExpenses.getId());
            MajorExpensesDetailsMapping mapping = new MajorExpensesDetailsMapping();
            mapping.setId(KeyGenerator.generateKey());
            mapping.setMajorExpenseId(majorExpenses.getId());
            mapping.setMajorExpenseDetailId(majorExpenseDetails.getId());
            mapping.setCreatedAt(date);
            mapping.setUpdatedAt(date);
            majorExpensesMappings.add(mapping);
        });
        majorExpensesMapper.insert(majorExpenses);

        majorExpenseDetailsMapper.batchInsert(majorExpensesList);

        majorExpensesDetailsMappingMapper.batchInsert(majorExpensesMappings);

        return 1;
    }

    @Override
    @Transactional
    public Integer updateExpense(String id, ExpenseRequest updatedExpense) {
        Date date = new Date();
        // 修改主表
        MajorExpenses record = new MajorExpenses();
        DataConvertUtils.convertDTO2DO(updatedExpense, record);
        record.setUpdatedAt(date);
        majorExpensesMapper.update(record);
        // 删除映射
        List<MajorExpensesDetailsMapping> majorExpensesDetailsMappings = majorExpensesDetailsMappingMapper.getDetailsByMajorExpenseId(id);
        List<String> mappingIds = majorExpensesDetailsMappings.stream().map
                (MajorExpensesDetailsMapping::getId).collect(Collectors.toList());
        if(CollectionUtils.isNotEmpty(mappingIds)) {
            majorExpensesDetailsMappingMapper.deleteByIds(mappingIds);
        }
        // 删除明细
        List<String> detaiIds = majorExpensesDetailsMappings.stream().map
                (MajorExpensesDetailsMapping::getMajorExpenseDetailId).collect(Collectors.toList());
        if(CollectionUtils.isNotEmpty(detaiIds)) {
            majorExpenseDetailsMapper.deleteByIds(detaiIds);
        }

        List<MajorExpenseDetails> majorExpensesList = new ArrayList<>();
        List<MajorExpensesDetailsMapping> majorExpensesMappings = new ArrayList<>();
        if(null != updatedExpense) {
            // 设置主键id
            List<Detail> details = updatedExpense.getDetails();
            DataConvertUtils.convertDOList2DTOList(details, majorExpensesList, MajorExpenseDetails.class);
        }
        majorExpensesList.stream().forEach(majorExpenseDetails -> {
            majorExpenseDetails.setCreatedAt(date);
            majorExpenseDetails.setUpdatedAt(date);
            // 设置主键id
            majorExpenseDetails.setId(KeyGenerator.generateKey());
            // 设置重大开销id
            majorExpenseDetails.setMajorExpenseId(id);
            MajorExpensesDetailsMapping mapping = new MajorExpensesDetailsMapping();
            mapping.setId(KeyGenerator.generateKey());
            mapping.setMajorExpenseId(id);
            mapping.setMajorExpenseDetailId(majorExpenseDetails.getId());
            mapping.setCreatedAt(date);
            mapping.setUpdatedAt(date);
            majorExpensesMappings.add(mapping);
        });
        majorExpenseDetailsMapper.batchInsert(majorExpensesList);

        majorExpensesDetailsMappingMapper.batchInsert(majorExpensesMappings);
        return 1;
    }

    @Override
    @Transactional
    public Integer deleteExpense(String id) {
        // 删除主表
        majorExpensesMapper.delete(id);
        // 查询映射
        List<MajorExpensesDetailsMapping> majorExpensesDetailsMappings = majorExpensesDetailsMappingMapper.getDetailsByMajorExpenseId(id);
        // 列表ids
        List<String> mappingIds = majorExpensesDetailsMappings.stream().map
                (MajorExpensesDetailsMapping::getId).collect(Collectors.toList());
        majorExpensesDetailsMappingMapper.deleteByIds(mappingIds);
        // 明细ids
        List<String> detaiIds = majorExpensesDetailsMappings.stream().map
                (MajorExpensesDetailsMapping::getMajorExpenseDetailId).collect(Collectors.toList());
        majorExpenseDetailsMapper.deleteByIds(detaiIds);
        return 1;
    }

    @Override
    public ExpenseResponse getExpenseDetails(String id) {
        ExpenseResponse expenseResponse = new ExpenseResponse();
        List<Detail> details = new ArrayList<>();
        MajorExpenses majorExpenses = majorExpensesMapper.select(id);
        if (majorExpenses != null) {
            DataConvertUtils.convertDO2DTO(majorExpenses, expenseResponse);
            // 查询详情信息列表
            List<MajorExpensesDetailsMapping> majorExpensesDetailsMappings = majorExpensesDetailsMappingMapper.getDetailsByMajorExpenseId(id);
            if(CollectionUtils.isNotEmpty(majorExpensesDetailsMappings)) {
                List<String> ids = majorExpensesDetailsMappings.stream().map
                        (MajorExpensesDetailsMapping::getMajorExpenseDetailId).collect(Collectors.toList());
                // 查询详情列表
                List<MajorExpenseDetails> majorExpenseDetails = majorExpenseDetailsMapper.getDetailsByIds(ids);
                DataConvertUtils.convertDOList2DTOList(majorExpenseDetails, details, MajorExpenseDetails.class);
            }
        }
        expenseResponse.setDetails(details);
        return expenseResponse;
    }
}
